﻿using IoTClient.Enums;
using IoTClient.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Serialization;

/*******************************************ModbusRtuClient扩展*************************************************************/

namespace IoTClient.Clients.Modbus
{
    /// <summary>
    ///
    /// </summary>
    public partial class ModbusRtuClient
    {
        /// <summary>
        ///
        /// </summary>
        public ModbusRtuClient()
        {
        }

        /// <summary>
        /// 站号
        /// </summary>
        [JsonProperty("站号"), DisplayName("站号")] public byte StationNumber { get; set; } = 1;

        /// <summary>
        /// 多去读取用
        /// </summary>
        [XmlIgnore, Browsable(false)] public List<ModbusInput> ReadBatchAddressList { get; set; } = new List<ModbusInput>();

        private byte GetFunctionCode(ModbusStore store)
        {
            switch (store)
            {
                case ModbusStore.输入线圈:
                    return 3;

                case ModbusStore.输出线圈:
                    return 3;

                case ModbusStore.输入寄存区:
                    return 3;

                case ModbusStore.保持性存储区:
                    return 3;

                default:
                    return 3;
            }
        }

        /// <summary>
        /// 开一个线程,不停的去读取这个设备
        /// </summary>
        /// <returns></returns>
        public override Result Start()
        {
            Result result = new Result();
            ReadBatchAddressList = AllVarableList.Select(x => new ModbusInput()
            {
                DataType = x.DataType,
                StationNumber = StationNumber,
                FunctionCode = GetFunctionCode(x.ModbusStore),
                Address = x.Address,
            }).ToList();
            try
            {
                AllVarableDictionary = AllVarableList.ToDictionary(x => (Name + "_" + x.Address).ToUpper().Trim(), x => x);
                AllVarableList.ForEach(x => x.AlarmEnable = x.HHighAlarmEnable & x.HighAlarmEnable & x.LLowAlarmEnable & x.LowAlarmEnable);
                Task.Run(() =>
                {
                    while (!Cts.IsCancellationRequested)
                    {
                        if (Connected)
                        {
                            Result<List<ModbusOutput>> res = BatchRead(ReadBatchAddressList);

                            if (res.IsSucceed)
                            {
                                CycleTime = res.TimeConsuming;
                            }
                            else
                            {
                                Loger?.Invoke($"{this.Name}:BatchRead失败:{res.Err}", res.Exception);
                            }
                        }
                        else
                        {
                            if (IsFirstConnect)
                            {
                                var res = Open();
                                Loger?.Invoke($"{this.Name}:第一次连接{(res.IsSucceed ? "成功" : "失败")};", res.Exception);
                                Connected = res.IsSucceed;
                            }
                            else
                            {
                                Loger?.Invoke($"重连中.....一共重连了{ReconnectionCount}次");
                                Thread.Sleep(Timeout);
                                var res = Open();
                                Connected = res.IsSucceed;
                                Loger?.Invoke($"{this.Name}:第{ReconnectionCount}次重连{(res.IsSucceed ? "成功" : "失败")};异常消息:{res.Err}", res.Exception);
                                if (res.IsSucceed)
                                {
                                    ReconnectionCount = 0;
                                    Loger?.Invoke($"{this.Name}:第{ReconnectionCount}次重连成功;");
                                }
                                else
                                {
                                    ReconnectionCount++;
                                    Loger?.Invoke($"{this.Name}:第{ReconnectionCount}次重连失败;异常消息:{res.Err}", res.Exception);
                                }
                            }
                            IsFirstConnect = false;
                        }
                    }
                }, this.Cts.Token);
            }
            catch (Exception ex)
            {
                Loger?.Invoke($"{this.Name}初始化字典集合或者开启线程失败:{ex.Message}", ex);
                result.IsSucceed = false;
                result.Err = $"{this.Name}初始化字典集合或者开启线程失败";
                result.Exception = ex;
                return result;
            }
            result.IsSucceed = true;
            result.Err = $"{this.Name}:启动成功";
            return result;
        }
    }
}